import CoreBluetooth

class BLEManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    var centralManager: CBCentralManager!
    var esp32Car: CBPeripheral?
    var confirmCharacteristic : CBCharacteristic?
    var confirmPeripheral: CBPeripheral?
    
    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
          case .poweredOn:
              print("Bluetooth is On")
              startScanning()
          case .poweredOff:
              print("Bluetooth is Off")
          default:
              break
          }
    }
    func startScanning() {
        centralManager.scanForPeripherals(withServices: nil, options: nil)
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if let deviceName = advertisementData[CBAdvertisementDataLocalNameKey] as? String, deviceName.contains("ESP32-Car") {
            self.esp32Car = peripheral
            self.centralManager.stopScan()
            self.centralManager.connect(peripheral, options: nil)
        }
    }

    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?){
        print("Fail to esp32Car! \(error)")
        self.confirmPeripheral = nil
        self.confirmCharacteristic = nil
        centralManager.scanForPeripherals(withServices: nil, options: nil)
    }
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("Connected to esp32Car!")
        peripheral.delegate = self
        peripheral.discoverServices(nil)
    }
    //- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?){
        print("disconnect")
        self.confirmPeripheral = nil
        self.confirmCharacteristic = nil
        centralManager.scanForPeripherals(withServices: nil, options: nil)
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if let services = peripheral.services {
            for service in services {
                print("Discovered service: \(service.uuid.uuidString)")
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        if let characteristics = service.characteristics {
            for characteristic in characteristics {
                print("Discovered characteristic: \(characteristic.uuid.uuidString)")
                if characteristic.properties.contains(.write) {
                    self.confirmPeripheral = peripheral
                    self.confirmCharacteristic = characteristic
                    
                   
                }
            }
        }
    }
//    var onDataReceived: ((String) -> Void)?
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if let data = characteristic.value {
         print(data)
        }
    }
    func peripheral(_ peripheral:CBPeripheral, didWriteValueFor characteristic:CBCharacteristic,error: Error?){
        
        
    }
    func writeValue(data: String){
        if self.confirmPeripheral != nil && self.confirmCharacteristic != nil{
            print("BLE write: \(data)")
            self.confirmPeripheral!.writeValue(data.data(using: .utf8)!, for: self.confirmCharacteristic!, type: .withResponse)
        }
      
    }

}
